#!/usr/bin/env lua

-- Lua到GAS汇编转换器（AT&T语法64位版本）
-- 用法: ./luacpr.lua <input.lua> [output.s]

local function read_file(filename)
    local file = io.open(filename, "r")
    if not file then
        error("无法打开文件: " .. filename)
    end
    local content = file:read("*a")
    file:close()
    return content
end

local function write_file(filename, content)
    local file = io.open(filename, "w")
    if not file then
        error("无法创建文件: " .. filename)
    end
    file:write(content)
    file:close()
end

local function lua_to_gas_att64(lua_code)
    local gas_output = {}
    
    -- GAS汇编头部 (AT&T语法，64位) - 兼容BUSYBOX+MING64环境
    table.insert(gas_output, "# Generated by Luacpr / For The WinKit / BUSYBOX+MING64 Environment")
    table.insert(gas_output, ".data")
    table.insert(gas_output, "")
    
    -- 将Lua代码分割为行
    local lines = {}
    for line in lua_code:gmatch("([^\n]*)\n?") do
        if line ~= "" then
            table.insert(lines, line)
        end
    end
    
    -- 将每行Lua代码作为字符串常量输出
    for i, line in ipairs(lines) do
        -- 转义特殊字符
        line = line:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("'", "\\'")
        table.insert(gas_output, "line" .. i .. ":")
        table.insert(gas_output, '    .asciz "' .. line .. '\\n"')
    end
    table.insert(gas_output, "")
    
    -- 主代码段
    table.insert(gas_output, ".text")
    table.insert(gas_output, ".globl main")  -- MINGW使用main而不是_start
    table.insert(gas_output, "")
    table.insert(gas_output, "main:")
    
    -- 视窗64位环境的栈帧设置
    -- 使用视窗64位fastcall调用约定：第一个参数放在rcx中
    table.insert(gas_output, "    pushq %rbp")
    table.insert(gas_output, "    movq %rsp, %rbp")
    table.insert(gas_output, "    subq $32, %rsp")  -- 分配栈空间
    table.insert(gas_output, "    call __main")      -- 调用初始化函数
    table.insert(gas_output, "")
    
    for i = 1, #lines do
        table.insert(gas_output, "    # 输出行 " .. i)
        table.insert(gas_output, "    leaq line" .. i .. "(%rip), %rcx")  -- 视窗64位：第一个参数放入rcx
        table.insert(gas_output, "    call puts")  -- 调用C标准库的puts函数
        table.insert(gas_output, "")
    end
    
    -- 退出程序
    table.insert(gas_output, "    # 退出程序")
    table.insert(gas_output, "    movl $0, %eax")  -- 返回值0
    table.insert(gas_output, "    addq $32, %rsp")  -- 释放栈空间
    table.insert(gas_output, "    popq %rbp")
    table.insert(gas_output, "    ret")
    
    -- 添加一个空行以确保文件以换行符结束
    table.insert(gas_output, "")
    
    return table.concat(gas_output, "\n")
end

-- 主程序
local function main()
    if #arg < 1 then
        print("用法: ./luacpr.lua <input.lua> [output.s]")
        os.exit(1)
    end
    
    local input_file = arg[1]
    local output_file = arg[2] or "output.s"
    
    -- 读取Lua文件
    local lua_code = read_file(input_file)
    
    -- 转换为GAS汇编 (AT&T语法，64位)
    local gas_code = lua_to_gas_att64(lua_code)
    
    -- 写入输出文件
    write_file(output_file, gas_code)
    
    print("转换完成! 输出文件: " .. output_file)
    print("使用以下命令汇编: gcc -c " .. output_file .. " -o output.o")
    print("然后链接: gcc output.o -o output.exe")
    print("注意: 在WinKit环境中使用GCC编译链接以确保兼容性")
end

-- 运行主程序
main()
